package arbitrage;

public class Match {
	
	// Nombre maximal de tours
	final static int MAXROUNDSNUMBER = 1000000;
	
	// Taille maximum d'un programme
	final static int MAXPROGLENGTH = 100;
	
	private VirtualMachine vm;
	private int positionRelative;
	public ProcessList proc1;
	public ProcessList proc2;
	private boolean matchImpair;
	private int resultat;
	
   // Ce champ indique si on est au tour impair.
	private boolean tour;
    
    public Match(int i) {
    	vm = new VirtualMachine();
       // Sans perte la généralité, on charge toujours le 1er programme à partir de la ligne 0 de la mémoire. Puis le 2e programme est chargé à partir d'une position relative engendrée par un générateur du nombre aléatoire.
    	positionRelative = MAXPROGLENGTH + (int) (Math.random()*(VirtualMachine.M - 2 * MAXPROGLENGTH));
    	proc1 = new ProcessList();
    	proc2 = new ProcessList();
    	matchImpair = (i%2 == 1);
    	tour = matchImpair;
    	resultat = -1;
    }
    
    // Remplir les mémoires
    public void set(MotMemoire[] prog1, MotMemoire[] prog2) {
    	proc1.add(0);
    	proc2.add(positionRelative);
    	for (int i=0; i<VirtualMachine.M; i++) {
    		vm.setAddress(i, Inst.DAT, 0, Mode.IM, 0, Mode.IM);
    	}
    	for (int i=0; i<MAXPROGLENGTH; i++) {
    		vm.setAddress(i, prog1[i].op, prog1[i].a, prog1[i].ma, prog1[i].b, prog1[i].mb);
    		vm.setAddress((positionRelative + i) % VirtualMachine.M, 
    				prog2[i].op, prog2[i].a, prog2[i].ma, prog2[i].b, prog2[i].mb);
    	}
    }
    
    // Jouer jusqu'à obtenir un résultat
	public int playAll() {
		
		int c = 0;
		
		try {
        	for (int j = 0 ; j < 2*MAXROUNDSNUMBER ; j++) {
        		c++;
        		play();
        	}
        	// On a l'égalite si le MAXROUNDSNUMBER est atteint.
        	resultat = 0;
    	}
		catch (EmptyProcessListException e) {
			if (tour) {
				// La liste du 1er joueur est vide, le joueur 2 gagne. 
				resultat = 2;
			}
			else {
				// La liste du 2e joueur est vide, le joueur 1 gagne.
				resultat = 1;
			}
		}
		
		return c;
	}
	
   // Forcer à jouer le 1er joueur même si ce n'est pas son tour
	public void playPlayer1() throws EmptyProcessListException {
		vm.execute(proc1);
	}
	
   // Forcer à jouer le 2e joueur même si ce n'est pas son tour
	public void playPlayer2() throws EmptyProcessListException {
		vm.execute(proc2);
	}
	
   // Jouer le prochain tour
	public void play() throws EmptyProcessListException {
		if (tour) {
			vm.execute(proc1);
		}
		else {
			vm.execute(proc2);
		}
		
		tour = !tour;
	}
    
	public int resultat() {return resultat;}
	
	public boolean getTour() {
		return tour;
	}
	
	public VirtualMachine getVM(){
		return this.vm;
	}
	
}